package Network;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.Timer;

/**
 * Метод организующий добавление ведомых серверов к арбитру в случае если
 * ведомые серверы не были запущены в момент запуска сервера арбитра или
 * они были не доступны
 * @author volk ID = 1001
 */
public class ReconnectService {
  //--------------------Константы класса---------------------------------------
  static final public int DEFAULT_TIME = 10000; //Время по умолчанию
  //--------------------Аттрибуты класса---------------------------------------
  private Timer timer = null; //Таймер по которому будет производится пингование
  private int time = DEFAULT_TIME; //Время запроса к ведомому серверу
  private ArbitrationController asc; //Контроллер текущего арбитра
  private NetworkAddress address; //Удалённый адрес арбитра
  private boolean  state = true; //Нужно ли осуществлять попытке подключения
  //Список обработчиков события "Проблемный сервер удалось добавить"
  private LinkedList<ActionListener> lstAddServer = new LinkedList<ActionListener>();
  //---------------------Сервисные методы----------------------------
  /**
   * Инициализировать параметры таймера
   */
  private void initTimer(){
   if(timer != null) return;
   ActionListener listener = new ActionListener(){
    public void actionPerformed(ActionEvent e) {
     if(!state) return;
     try{
      if(asc.addNewSlaveServer(address) != null){
       state = false;
       Iterator<ActionListener> iter = lstAddServer.iterator();
       e.setSource(address);
       while(iter.hasNext()){
        iter.next().actionPerformed(e);
       }
      }
     }catch(Exception ex){
      System.out.println("Сервер по прежнему не доступен, IP: "+address.getHost() + " Порт: " + address.getPort());
     }
    }
   };
   timer = new Timer(time,listener);
  }
  //--------------------Интерфейсные методы------------------------------------
  /**
   * Конструктор класса (в качестве времени дискретизации используется значение константы DEFAULT_TIME)
   * @param controller контроллер сервера арбитра
   * @param address  адрес сервера, который необходимо подключить
  */
  public ReconnectService(ArbitrationController controller, NetworkAddress address){
    this(controller, address, DEFAULT_TIME);
  }


  /**
   * Конструктор класса
   * @param controller контроллер сервера арбитра
   * @param address  адрес сервера, который необходимо подключить
   * @param time период дискретизации пингования
   */
  public ReconnectService(ArbitrationController controller, NetworkAddress address, int time){
   asc = controller;
   this.time = time;
   this.address = address;
   initTimer();
  }

  /**
   * Полчить интервал пинга
   * @return интервал пинга
   */
  public int getDelay(){
   return time;
  }

  /**
   * Установит интервал пинга
   * @param delay - новый интервал пинга
   */
  public void setDelay(int delay){
   this.time = delay;
   initTimer();
  }


  /**
   * Начало пинга
   */
    public void startPing(){
        System.out.println("DEBUG: start ping ReconnectService");
        initTimer();
        timer.start();
    }

   /**
    * Приостановить пинг
    */
    public void stopPing(){
        if(timer!=null) {
            timer.stop();
            System.out.println("DEBUG: stop ping ReconnectService");
        }
    }

    /**
     * Добавить обработчик события "Сервер удалось подключить"
     * @param listener обработчик события
     */
    public void addServerConnectListener(ActionListener listener){
      lstAddServer.add(listener);
    }

  //----------------------------------------------------------------------------


}
